﻿#ifndef FINGERMODULE_H
#define FINGERMODULE_H

#include <QBitArray>
#include <QObject>
#include <QImage>
#include <QSerialPort>

#define FINGER_IMG_WIDTH  256 //指纹图像宽度.
#define FINGER_IMG_HEIGHT 288 //指纹图像高度.

#define REPLY_TIMEOUT_MS  600 //应答超时时间.

enum FingerCmd {
    VerifyPassword     = 0x13, //效验口令.
    ReadSysParam       = 0x0F, //读系统参数.
    ReadConList        = 0x1F, //读指纹模板索引表.
    TemplateNum        = 0x1D, //读指纹模板数.
    GenImg             = 0x01, //录指纹图像.
    GetEcho            = 0x53, //握手.
    AutoLogin          = 0x31, //自动登记.
    AutoSearch         = 0x32, //自动搜索.
    UpImage            = 0x0A, //上传图像.
    Img2Tz             = 0x02, //图像转特征.
    RegModel           = 0x05, //特征合成模板.
    Store              = 0x06, //存储模板.
    DeleteChar         = 0x0C, //删除模板.
    Empty              = 0x0D, //清空指纹库.
    Search             = 0x04, //搜索指纹.
    PsCancel           = 0x30, //取消指令.
};


struct DevSysParam{
    quint16 m_stateReg {0x0006}; //系统的状态寄存器内容.
    quint16 m_sysIdent {0x2FE8}; //固定值：0x0000.
    quint16 m_totalTempCnt {0x0032}; //指纹库容量.
    quint16 m_safeRank {0x0003}; //安全等级代码（1、2、3、4、5），可设置参数5
    quint32 m_address {0xFFFFFFFF};  //32位设备地址.
    quint16 m_packSize {0x0002}; //数据包大小代码（0->32、1->64、2->128、3->256），可设置参数6
    quint16 m_bitRate {0x0006};  //波特率为9600×N bps，可设置参数4
};

//指纹模块的指令交互类.
class FingerModule : public QObject
{
    Q_OBJECT
public:
    explicit FingerModule(QObject *parent = nullptr);
    ~FingerModule();
    bool openSerialPort(qint32 baudRate, QString &errInfo);

    void resetModule();
    int getFreeTempId(); //获取空闲的指纹模板Id.

    struct DevSysParam m_sysParam; //系统参数.
    QImage m_fingerImg;   //指纹图像.

    QBitArray m_conList; //指纹模板索引表.
    int m_usedTempCnt {0}; //模块使用的模板数量.
    qint16 m_searchPage {-1}; //搜索目标指纹编号.
    qint16 m_searchScore {0}; //搜索目标指纹对比得分.

signals:
    void sigShowMsg(QString errInfo);
    void sigUpImageOver(); //上传图像结束，可访问成员m_fingerImg获取.
    void sigReadConListOver();
    void sigAutoLoginOver(bool flag, int tempId, QString info); //注册结束.
    void sigAutoSearchOver(bool flag, int tempId, QString info); //搜索结束.

public slots:
    void onSendCtrlCmd(int ctrlCmd, int param1=-1, int param2=-1, int param3=-1, int param4=-1);

private:
    qint8 checkSingleReply(int ctrlCmd, QString &errInfo); //处理简单应答.

    void thReadSysParam(QByteArray cmd);
    void thReadConList(QByteArray cmd);
    void thReadTemplate(QByteArray cmd);
    void thAutoLogin(QByteArray cmd, int tempId);  //切换为自动登记模式，被动退出.
    void thAutoSearch(QByteArray cmd); //切换为自动搜索模式，被动退出.
    void thUpImage(QByteArray cmd);
    void thSearch(QByteArray cmd);

    void modifyCheckSum(QByteArray &cmd); //修正校验和.
    QString getCmdNameStr(int ctrlCmd);

private:
    QSerialPort *m_serial {nullptr};

    quint16 m_packHead {0xEF01}; //协议包头.
    quint32 m_address  {0xFFFFFFFF}; //模块地址.

    volatile bool m_processing {false};
};

#endif // FINGERMODULE_H
